﻿using System;
using System.Collections.Generic;
using SlimDX.Direct3D9;
using D3D9 = SlimDX.Direct3D9;
using ShaderFlags = SlimDX.D3DCompiler.ShaderFlags;

namespace HlslCompiler
{
    internal class Compiler09
        : ICompiler
    {
        public List<Feedback> Compile(string code, CompilerSettings settings)
        {
            var feedback = GetFeedback(code, settings);
            return feedback != null ? FeedbackParser.Parse(feedback) : null;
        }

        private string GetFeedback(string code, CompilerSettings settings)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(code)) throw new Exception("There is no code to compile.");
                var bcode = D3D9.ShaderBytecode.Compile(code, "PointSprites", settings.Profile, GetD3D9Flags(settings.ShaderFlags));
            }
            catch (Exception exception)
            {
                if (string.IsNullOrWhiteSpace(exception.Message)) return "Unspecified compilation error.";
                return exception.Message;
            }
            return null;
        }

        private D3D9.ShaderFlags GetD3D9Flags(ShaderFlags shaderFlags)
        {
            var result = D3D9.ShaderFlags.None;
            if (shaderFlags.HasFlag(ShaderFlags.None)) result &= D3D9.ShaderFlags.None;
            if (shaderFlags.HasFlag(ShaderFlags.Debug)) result &= D3D9.ShaderFlags.Debug;
            if (shaderFlags.HasFlag(ShaderFlags.OptimizationLevel3)) result &= D3D9.ShaderFlags.OptimizationLevel3;
            if (shaderFlags.HasFlag(ShaderFlags.OptimizationLevel2)) result &= D3D9.ShaderFlags.OptimizationLevel2;
            if (shaderFlags.HasFlag(ShaderFlags.OptimizationLevel1)) result &= D3D9.ShaderFlags.OptimizationLevel1;
            if (shaderFlags.HasFlag(ShaderFlags.OptimizationLevel0))
                result &= D3D9.ShaderFlags.OptimizationLevel0;
            if (shaderFlags.HasFlag(ShaderFlags.EnableIEEEStrictness))
                result &= D3D9.ShaderFlags.IeeeStrictness;
            if (shaderFlags.HasFlag(ShaderFlags.EnableBackwardsCompatibility))
                result &= D3D9.ShaderFlags.EnableBackwardsCompatibility;
            if (shaderFlags.HasFlag(ShaderFlags.PreferFlowControl))
                result &= D3D9.ShaderFlags.PreferFlowControl;
            if (shaderFlags.HasFlag(ShaderFlags.AvoidFlowControl))
                result &= D3D9.ShaderFlags.AvoidFlowControl;
            if (shaderFlags.HasFlag(ShaderFlags.NoPreshader))
                result &= D3D9.ShaderFlags.NoPreshader;
            if (shaderFlags.HasFlag(ShaderFlags.ForceSoftwarePixelShader))
                result &= D3D9.ShaderFlags.ForcePSSoftwareNoOpt;
            if (shaderFlags.HasFlag(ShaderFlags.ForceSoftwareVertexShader))
                result &= D3D9.ShaderFlags.ForceVSSoftwareNoOpt;
            if (shaderFlags.HasFlag(ShaderFlags.PartialPrecision))
                result &= D3D9.ShaderFlags.PartialPrecision;
            if (shaderFlags.HasFlag(ShaderFlags.PackMatrixColumnMajor))
                result &= D3D9.ShaderFlags.PackMatrixColumnMajor;
            if (shaderFlags.HasFlag(ShaderFlags.PackMatrixRowMajor))
                result &= D3D9.ShaderFlags.PackMatrixRowMajor;
            if (shaderFlags.HasFlag(ShaderFlags.SkipOptimization))
                result &= D3D9.ShaderFlags.SkipOptimization;
            if (shaderFlags.HasFlag(ShaderFlags.SkipValidation)) result &= D3D9.ShaderFlags.SkipValidation;
            return result;
        }

    }
}